#!/usr/bin/env python
# -*- coding: utf-8 -*-
# coding=utf-8
#
# TODO: 1. version apply.
# TODO: 2. eclipse apply.
#
# Copyright 2012-2013 by yfyang. All Rights Reserved.
import os
import getopt
import sys
import os.path
import shutil
import errno
import uuid

reload(sys)
# 解决：中文字符写入文件问题
sys.setdefaultencoding('utf-8')

gen_path = os.path.normpath(os.path.dirname(os.path.realpath(sys.argv[0])))

sys.path.append(os.path.join(gen_path, 'pym'))

from jinja2 import Environment, FileSystemLoader


def project_layout_gen(project_dir, project_name):
    # Maven layout project.
    _src = os.path.join(project_dir, project_name, 'src')
    if os.path.exists(_src):
        print 'the %s is exist!' % os.path.jon(project_dir, project_name)
        sys.exit(1)
    os.makedirs(_src)
    main_ = os.path.join(_src, "main")
    os.mkdir(main_)
    java_ = os.path.join(main_, 'java')
    os.mkdir(java_)
    app_path = os.path.join(java_, 'app')
    os.mkdir(app_path)
    os.mkdir(os.path.join(app_path, "controllers"))
    os.mkdir(os.path.join(app_path, "models"))
    os.mkdir(os.path.join(app_path, "jobs"))
    os.mkdir(os.path.join(app_path, "interceptors"))
    os.mkdir(os.path.join(app_path, "validators"))
    os.mkdir(os.path.join(app_path, "dtos"))

    webapp_ = os.path.join(main_, 'webapp')
    os.mkdir(webapp_)
    os.mkdir(os.path.join(webapp_, 'static'))
    web_inf_ = os.path.join(webapp_, 'WEB-INF')
    os.mkdir(web_inf_)
    os.mkdir(os.path.join(web_inf_, 'views'))
    # os.mkdir(web_inf_ + os.sep + "lib")

    resources_ = os.path.join(main_, 'resources')
    os.mkdir(resources_)
    os.mkdir(os.path.join(resources_, 'sqlcnf'))

    test_ = os.path.join(_src, 'test')
    os.mkdir(test_)
    test_java_ = os.path.join(test_, 'java')
    os.mkdir(test_java_)
    os.mkdir(os.path.join(test_java_, 'app'))
    os.mkdir(os.path.join(test_, 'resources'))


def copy_deps_lib(proj_dir):
    storage_path = os.path.join(
        proj_dir, 'src', 'main', 'webapp', 'WEB-INF', 'lib')
    copy_directory(os.path.join(gen_path, 'deps', 'compile'), storage_path)

    storage_path = os.path.join(proj_dir, 'src', 'test', 'lib')
    copy_directory(os.path.join(gen_path, 'deps', 'test'), storage_path)


def gen_idea(project_dir):
    # 1. get project name with application.conf
    application_name = read_app_name(project_dir)

    idea_ipr = application_name + '.ipr'
    idea_iws = application_name + '.iws'
    idea_iml = application_name + '.iml'
    params = {'appName': application_name, 'appSN': uuid.uuid4(), 'gen_path': gen_path}
    file_content = render_config_file('idea/app.module', params)
    _storage_file(project_dir, file_content, idea_iml)
    file_content = render_config_file('idea/app.project', params)
    _storage_file(project_dir, file_content, idea_ipr)
    file_content = render_config_file('idea/app.workspace', params)
    _storage_file(project_dir, file_content, idea_iws)
    print 'Convert the idea project Success.'


def gen_config(directory, application_name):
    storage_path = os.path.join(directory, 'src', 'main', 'resources')
    params = {'appName': application_name}

    file_content = render_config_file('conf/application.conf', params)
    _storage_file(storage_path, file_content, 'application.conf')

    file_content = render_config_file('conf/ehcache.xml', params)
    _storage_file(storage_path, file_content, 'ehcache.xml')

    file_content = render_config_file('conf/logback.xml', params)
    _storage_file(storage_path, file_content, 'logback.xml')


def create_maven(maven_project_path, group):
    params = {'group': group}

    file_content = render_config_file('ci/maven.project', params)
    _storage_file(maven_project_path, file_content, 'pom.xml')


def _storage_file(storage_path, content, file_name):
    output = open(storage_path + os.sep + file_name, 'wb')
    output.write(content)
    output.close()


def render_config_file(template_name, kwargs):
    env = Environment(
        # loader是加载器类，用来加载模板文件。
        loader=FileSystemLoader(os.path.join(gen_path, 'templates')),
        auto_reload=True,  # 自动重载，调试用
        # 还有许多参数，例如缓存大小，详细见jinja2文档
    )
    # 创建一个template对象。
    template = env.get_template(template_name)
    # 进行渲染，返回HTML字符串。
    return template.render(kwargs)


def copy_directory(source_dir, dest_dir):
    try:
        shutil.copytree(source_dir, dest_dir)
    except OSError as exc:  # python >2.5
        if exc.errno == errno.ENOTDIR:
            shutil.copy(source_dir, dest_dir)
        else:
            raise


def init_default_code(directory, project_name):
    # .gitignore copy
    ignore_git = open(os.path.join(gen_path, 'deps', 'git', 'ignore'), 'r')
    _storage_file(directory, ignore_git.read(), '.gitignore')
    ignore_git.close()

    storage_path = os.path.join(
        directory, "src", "main", "java", "app", "controllers")

    params = {'appName': project_name}

    file_content = render_config_file('code/IndexController.java', params)
    _storage_file(storage_path, file_content, 'IndexController.java')

    storage_path = os.path.join(
        directory, "src", "main", "webapp", "WEB-INF", "views")

    file_content = render_config_file('code/index.ftl', params)
    _storage_file(storage_path, file_content, 'index.ftl')


def pack_war(project_dir):
    import subprocess

    application_name = read_app_name(project_dir)

    # 2. render build.xml file into project dir.
    build_xml_content = render_config_file('ci/build.xml', {'appName': application_name,'genPath': gen_path})
    build_xml_file = os.path.join(project_dir, 'build.xml')
    _storage_file(project_dir, build_xml_content, 'build.xml')

    # 3. call ant run subprocess.
    ant_path = os.path.join(gen_path, 'ci', 'ant', 'bin', 'ant')
    ant_cmds = '%s clean package' % ant_path
    compile_process = subprocess.Popen(ant_cmds, shell=True, stdout=subprocess.PIPE)
    while compile_process.poll() is None:
        print compile_process.stdout.readline()
    # 4. clean build file.
    os.remove(build_xml_file)


def read_app_name(project_dir):
    # 1. get project name with application.conf
    app_config_file = os.path.join(project_dir, 'src', 'main', 'resources', 'application.conf')

    if not os.path.isfile(app_config_file):
        print '%s does not seem an effective jfinal application.' % project_dir
        sys.exit()

    application_name = 'app'
    app_config = file(app_config_file, 'rU')
    for prop_line in app_config:
        prop_def = prop_line.strip()
        if len(prop_def) == 0:
            continue
        if prop_def[0] in ('!', '#'):
            continue
        punctuation = [prop_def.find(c) for c in ':= '] + [len(prop_def)]
        found = min([pos for pos in punctuation if pos != -1])
        prop_name = prop_def[:found].rstrip()
        if prop_name == 'app':
            application_name = prop_def[found:].lstrip(":= ").rstrip()
            break
    return application_name


def usage():
    print "~ "
    print "~ JFinal App gen."
    print "~ Usage: jfgen cmd application_name [-options]"
    print "~"
    print '~ with,  new      Create a new application'
    print '~        war      Export the application as a standalone WAR archive'
    print '~        idea     Convert the project to Intellij IDEA project'
    print '~        help     Show jfgen help'
    print '~'


if __name__ == "__main__":
    if len(sys.argv) < 2:
        usage()
        sys.exit()
    try:
        options, args = getopt.getopt(
            sys.argv[2:], "hd:", ["help", "dir="])
    except getopt.GetoptError:
        sys.exit()

    cmd = sys.argv[1].lower()
    if cmd is None:
        usage()
        sys.exit()

    for name, value in options:
        if name in ("-h", "--help"):
            usage()
        if name in ("-d", "--dir"):
            app_dir = value
    app_dir = os.getcwd()

    if cmd == 'new':
        app_name = sys.argv[2]
        if app_name is None:
            usage()
            sys.exit()
        project_layout_gen(app_dir, app_name)

        project_folder = os.path.join(app_dir, app_name)
        # copy_deps_lib(project_folder)

        gen_config(project_folder, app_name)

        create_maven(project_folder, app_name);

        init_default_code(project_folder, app_name)

        # gen_idea(project_folder, app_name)

        print '%s project create Success!' % app_name
        sys.exit()

    if cmd == 'war':
        pack_war(app_dir)
        sys.exit()

    if cmd == 'idea':
        gen_idea(app_dir)
        sys.exit()

    if cmd == 'help':
        usage()
        sys.exit()

    usage()
    sys.exit()

